/*
 * UMediaFrameQueue.cpp
 *
 *  Created on: 2020年7月11日
 *      Author: terry
 */

#include "UMediaFrameQueue.h"
#include <deque>
#include <mutex>
#include <atomic>

typedef std::deque< UMediaFrame >		UMediaFrameDeque;


class UMediaFrameQueuePrivate
{
public:
	UMediaFrameQueuePrivate():
		m_maxSize(25)
	{
	}

	~UMediaFrameQueuePrivate()
	{
	}

	size_t size()
	{
		std::lock_guard< std::mutex>	lock(m_mutex);
		return m_frames.size();
	}

	bool empty()
	{
		return size() == 0;
	}

	size_t push(UMediaFrame& frame)
	{
		std::lock_guard< std::mutex>	lock(m_mutex);
		m_frames.push_back(frame);

		if (m_frames.size() > m_maxSize)
		{
			m_frames.pop_front();
		}

		return m_frames.size();
	}

	bool pop(UMediaFrame& frame)
	{
		bool got = false;
		std::lock_guard< std::mutex>	lock(m_mutex);
		if (m_frames.size() > 0)
		{
			frame = m_frames.front();
			m_frames.pop_front();
			got = true;
		}
		return got;
	}

	void clear()
	{
		std::lock_guard< std::mutex>	lock(m_mutex);
		m_frames.clear();
	}

	void setMaxSize(size_t maxSize)
	{
		std::lock_guard< std::mutex>	lock(m_mutex);
		m_maxSize = maxSize;
	}

	size_t getMaxSize()
	{
		std::lock_guard< std::mutex>	lock(m_mutex);
		return m_maxSize;
	}

	size_t dropUntil(size_t maxSize)
	{
		size_t count = 0;
		std::lock_guard< std::mutex>	lock(m_mutex);
		while (m_frames.size() > maxSize)
		{
			m_frames.pop_front();
			count ++;
		}
		return count;
	}

	UMediaFrameDeque	m_frames;
	std::mutex	m_mutex;
	size_t	m_maxSize;

};



UMediaFrameQueue::UMediaFrameQueue():
	m_pimpl(new UMediaFrameQueuePrivate())
{
}

UMediaFrameQueue::~UMediaFrameQueue()
{

	delete m_pimpl;
}


size_t UMediaFrameQueue::size()
{
	return m_pimpl->size();
}

bool UMediaFrameQueue::empty()
{
	return m_pimpl->empty();
}

size_t UMediaFrameQueue::push(UMediaFrame& frame)
{
	return m_pimpl->push(frame);
}

bool UMediaFrameQueue::pop(UMediaFrame& frame)
{
	return m_pimpl->pop(frame);
}

void UMediaFrameQueue::clear()
{
	m_pimpl->clear();
}

void UMediaFrameQueue::setMaxSize(size_t maxSize)
{
	m_pimpl->setMaxSize(maxSize);
}

size_t UMediaFrameQueue::getMaxSize()
{
	return m_pimpl->getMaxSize();
}

size_t UMediaFrameQueue::dropUntil(size_t maxSize)
{
	return m_pimpl->dropUntil(maxSize);
}